#include "SystemCollection.h"
#include "IEngineSystem.h"

SystemCollection::SystemCollection(void)
{
}

SystemCollection::~SystemCollection(void)
{
	
}

EnginePointer<IEngineSystem> SystemCollection::getSystem(GUID systemIdentifier)
{
	map<GUID, EnginePointer<IEngineSystem>, GUIDCmp>::iterator it = systems.find(systemIdentifier);
	if (it == systems.end())
	{
		return NULL;
	}
	else
	{
		return it->second;
	}
}

void SystemCollection::addSystem(EnginePointer<IEngineSystem>& system)
{
	bool empty = systems.empty();
	if (empty || systems.find(system->getSystemIdentifier()) == systems.end())
	{
		systems.insert(pair<GUID, EnginePointer<IEngineSystem>>(system->getSystemIdentifier(), system));
		systemsList.push_back(system);
	}
}

void SystemCollection::GenerateLevels()
{
	systemsLevelList.clear();
	lengthMap.clear();
	numberOfLevels = 0;

	for (map<GUID, EnginePointer<IEngineSystem>, GUIDCmp>::iterator it = systems.begin(); it != systems.end(); it++)
	{
		UINT length = GetLongestPathLength(it->second);
		if (length > numberOfLevels) numberOfLevels = length;
		if (systemsLevelList.size() <= length) systemsLevelList.resize(length+1);
		systemsLevelList[length].push_back(it->second);
	}
}

int SystemCollection::getNumberOfLevels()
{
	return numberOfLevels;
}

list<EnginePointer<IEngineSystem>>::iterator SystemCollection::begin()
{
	return systemsList.begin();
}

list<EnginePointer<IEngineSystem>>::iterator SystemCollection::end()
{
	return systemsList.end();
}

list<EnginePointer<IEngineSystem>>::iterator SystemCollection::levelBegin(int level)
{
	return systemsLevelList[level].begin();
}

list<EnginePointer<IEngineSystem>>::iterator SystemCollection::levelEnd(int level)
{
	return systemsLevelList[level].end();
}

int SystemCollection::GetLongestPathLength(EnginePointer<IEngineSystem> system)
{
	GUID guid = system->getSystemIdentifier();
	if (lengthMap.find(guid) == lengthMap.end())
	{
		int length = -1;

		list<GUID> dependencies = system->getDependencies();
		for (list<GUID>::iterator it = dependencies.begin(); it != dependencies.end(); it++)
		{
			int dependencyLength = GetLongestPathLength(getSystem(*it));
			if (dependencyLength > length) length = dependencyLength;
		}
		lengthMap[guid] = ++length;
	}
	return lengthMap[guid];
}